package com.cqndt.disaster.device.warn;

import com.cqndt.disaster.device.dao.*;
import com.cqndt.disaster.device.dao.warn.WarnPlanMapper;
import com.cqndt.disaster.device.dao.warn.WarnYlSettingMapper;
import com.cqndt.disaster.device.domain.*;
import com.cqndt.disaster.device.message.SudasSmsUtil;
import com.cqndt.disaster.device.utils.DateUtil;
import com.cqndt.disaster.device.vo.TabMsgRecord;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.text.MessageFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 雨量预警判断
 *
 * @Author yin_q
 * @Date 2019/9/11 10:14
 * @Email yin_qingqin@163.com
 **/
@Component
@Slf4j
public class YlWarn {

    @Autowired
    WarnYlSettingMapper warnYlSettingMapper;

    @Autowired
    WarnPlanMapper warnPlanMapper;

    @Autowired
    TabDeviceMapper tabDeviceMapper;

    @Autowired
    TbsYlMapper tbsYlMapper;

    @Autowired
    TabMonitorMapper tabMonitorMapper;

    @Autowired
    TabAlarmInfoMapper tabAlarmInfoMapper;

    @Autowired
    TabMsgRecordMapper tabMsgRecordMapper;

    @Resource
    private StringRedisTemplate stringRedisTemplate;

    @Async("taskExecutor")
    @Scheduled(initialDelay = 10000, fixedDelay = 10000)
    public void executePlan(){

        log.info("雨量检测仪预警->开始进行雨量检测仪预警判断");

        // 取出待判断得告警信息
        List<WarnPlan> warnPlanList = warnPlanMapper.queryWarnPlan(4);

        for(WarnPlan warnPlan : warnPlanList){
            // 删除本次预警判断
            warnPlanMapper.deleteWarnPlanById(warnPlan.getId());

            /**
             * 预警逻辑
             * 1.取出对应设备得预警阈值信息，如无对应设备得预警信息则不进行后续判断
             * 2.分别判断对应阈值信息，看是否达到预警条件
             * 规定时间内，所有降雨量数据相加是否大于等于设置得值
             * 3.满足阈值信息时，则进行短信人员筛选，并发送对应短信内容
             * 4.存储和推送对应预警信息，以及对应短信信息
             */

            /*
             * 第一步，判断是否存在预警信息
             */
            TabDevice tabDevice = tabDeviceMapper.getDevice(warnPlan.getSensorNo());

            if(tabDevice == null){
                log.info("雨量检测仪预警->设备{}，暂无设备信息，不进行预警判断！", warnPlan.getSensorNo());
                continue;
            }

            List<WarnYlSetting> warnYlSettingList = warnYlSettingMapper.queryWarnYlSettingList(String.valueOf(tabDevice.getId()));

            if(warnYlSettingList == null || warnYlSettingList.isEmpty()){
                log.info("雨量检测仪预警->设备{}，暂无阈值信息，不进行预警判断！", warnPlan.getSensorNo());
                continue;
            }

            /**
             * 开始进行告警判断，优先进行紧急得判断，一旦达到预警条件，后续判断则不在进行判断
              */
            for(WarnYlSetting warnYlSetting : warnYlSettingList){
                // 得到指定时间之前的时间点
                String startDate = DateUtil.getBeforeByHourTime(warnYlSetting.getHours());

                String endDate = DateUtil.dateToString(new Date());

                Double ylValue = tbsYlMapper.getSumValueByDate(startDate, endDate, warnPlan.getSensorNo());

                if(new BigDecimal(ylValue).compareTo(warnYlSetting.getValue()) < 0){
                    log.info("雨量检测仪预警->设备{}，未达到触发{}小时降雨量{}条件，不继续进行预警判断！", warnPlan.getSensorNo(), warnYlSetting.getHours(), warnYlSetting.getValue());
                    continue;
                }

                /**
                 * 达到预警条件，进行短信发送
                 */
                String projectName = tabMonitorMapper.getProjectNameByDeviceId(tabDevice.getId());

                String color = warnYlSetting.getLevel() == 1 ? "红色告警" : (warnYlSetting.getLevel() == 2 ? "橙色告警" : (warnYlSetting.getLevel() == 3 ? "黄色告警" : (warnYlSetting.getLevel() == 4 ? "蓝色告警" : "")));

                // 设备名称
                String deviceName = tabDevice == null ? "" : tabDevice.getDeviceName();

                String smsContent = MessageFormat.format("{0}监测:{1}设备,设备编号:{2},在{3}小时内,降雨量达到{4}{5},触发{6},请及时关注,监测时间:{7}",
                        projectName,
                        deviceName,
                        tabDevice.getDeviceNo(),
                        warnYlSetting.getHours(),
                        ylValue,
                        warnYlSetting.getUnit(),
                        color,
                        endDate);

                // 告警短信发送人员列表
                List<Map<String, Object>> personsList = tabAlarmInfoMapper.getAlarmPersons();

                // 去除重复短信发送
                Map<String, String> phoneMap = new HashMap<>();

                for (Map<String, Object> personInfo : personsList) {
                    String phone = personInfo.get("phone").toString();
                    String name = personInfo.get("name").toString();
                    Integer personLevel = Integer.valueOf(personInfo.get("level").toString());
                    Integer type = Integer.valueOf(personInfo.get("type").toString());
                    if (type == 4 || type == 1) {
                        // 反向判断，人员上的值是 4 红  3  橙  2 黄  1 蓝
                        Integer lv = warnYlSetting.getLevel() == 1 ? 4 : (warnYlSetting.getLevel() == 2 ? 3 : (warnYlSetting.getLevel() == 3 ? 2 : 1));
                        if (lv >= personLevel) {
                            phoneMap.put(phone, name);
                        }
                    }
                }

                /**
                 * 发送短信
                 */
                int count = 0;
                for(Map.Entry<String, String> entry : phoneMap.entrySet()){
                    SudasSmsUtil.send(entry.getKey(), smsContent);
                    TabMsgRecord tabMsgRecord = new TabMsgRecord();
                    tabMsgRecord.setSendPerson("yunnanAdmin");
                    tabMsgRecord.setPhone(entry.getKey());
                    tabMsgRecord.setSendState(1);
                    tabMsgRecord.setContent(smsContent);
                    tabMsgRecord.setSendWay(1);
                    tabMsgRecord.setSendTime(new Date());
                    tabMsgRecordMapper.addTabMsgRecord(tabMsgRecord);
                    count++;
                }

                log.info("雨量检测仪预警->设备{},发送短信成功，本次发送短信数量{}", tabDevice.getDeviceNo(), count);

                /**
                 * 保存预警信息
                 */
                int monitorId = tabMonitorMapper.selectIdByDeviceNo(tabDevice.getId());
                insertAlarm(tabDevice.getDeviceNo(), new Date(), warnYlSetting.getLevel(), Double.valueOf(ylValue), monitorId, 2, smsContent);
            }

        }

    }

    /**
     * 存入告警信息
     * @param sensorNo  设备编号  deviceNo
     * @param warnTime  告警时间
     * @param level  告警等级
     * @param value  告警值
     * @param monitorId  监测ID
     * @param type  告警类型
     * @param smsContent  告警短信内容
     */
    private void insertAlarm(String sensorNo, Date warnTime, int level, Double value, int monitorId, int type, String smsContent) {
        TabAlarmInfo tabAlarmInfo = new TabAlarmInfo();
        tabAlarmInfo.setSensorNo(sensorNo);
        tabAlarmInfo.setMonitoringId(monitorId);
        tabAlarmInfo.setTime(warnTime);
        tabAlarmInfo.setValue(value);
        tabAlarmInfo.setLevel(level == 1 ? 4 : (level == 2 ? 3 : (level == 3 ? 2 : 1)));
        tabAlarmInfo.setAlarmType(type);
        tabAlarmInfo.setStatus(1);
        tabAlarmInfo.setUploadSend(0);
        tabAlarmInfo.setSmsContent(smsContent);
        tabAlarmInfoMapper.insertSelective(tabAlarmInfo);
    }

}
